

"""\
It supports to expand the file list inside the TAR files.

It provides two views to list the contents: one is the file
ordered in the TAR file and the other is the list organized
with its directory layout.

It also supports the file extension expansion for some specified
usage like tpl and thm to sharp the file choices.
"""

import time

__version__ = "1.10"

__aof__ = ('GNU Tar', 'TAR')
__extension__ = (('TAR package Files', ('*.tar',)),)


class _TarDecoder:
    def Execute(self, source, target, notify, **args):
        def _nullString(nb, data, **args):
            k = len(data) - 1
            while k >= 0:
                if ord(data[k]) != 0:
                    return data[:k+1]
                k -= 1

            return ''

        def _digit8(nb, data, **args):
            try:
                return int(_nullString(nb, data, **args), 8)
            except ValueError:
                return 0

        def _spDate(nb, data, **args):
            return time.ctime(_digit8(nb, data, **args))

        _HEADER = (
            ('Name', 100, 'object,export', {'function': _nullString}),
            ('Mode', 8, 'object', {'function': _nullString}),
            ('Uid', 8, 'object', {'function': _nullString}),
            ('Gid', 8, 'object', {'function': _nullString}),
            ('Size', 12, 'object,export', {'function': _digit8}),
            ('mtime', 12, 'object', {'function': _spDate}),
            ('chksum', 8, 'value'),
            ('typeflag', 1, 'value'),
            ('linkname', 100, 'object', {'function': _nullString}),
            ('Magic', 6, 'string,verify', {'verified': 'ustar '}),
            ('Version', 2, 'value'),
            ('uname', 32, 'object', {'function': _nullString}),
            ('gname', 32, 'object', {'function': _nullString}),
            ('devmajor', 8, 'object', {'function': _nullString}),
            ('devminor', 8, 'object', {'function': _nullString}),
            ('prefix', 155, 'object', {'function': _nullString}),
            ('junk', 12, 'object', {'function': _nullString})
        )

        ret = True
        entry = target.getEntry()
        start = args.get('start', 0)
        args['offset'] = 0

        while ret:
            ret, obj, consumed, _, exported = target.parse(
                'Header', _HEADER, afile=source, **args)
            if ret:
                size = int(exported[1])
                offset = start + args['offset']
                objectp = target.newItemObject(
                    exported[0],
                    field=target.newFieldObject(offset, consumed + size))

                objectp.appendChildren(obj)
                objectp.appendChildren(
                    target.newItemObject(
                        'Data',
                        attribute='extractable',
                        field=target.newFieldObject(offset + consumed, size)))
                entry.append(objectp)

                args['offset'] += consumed + size

        return entry.hasChildren()


def fmtService():
    return _TarDecoder
